/**************************************************************************//**
 * @file    CycloneDoubleLinkedList.c
 * @author  İsmail SEZEN (email: sezenismail@gmail.com)
 * @date    08-02-2011
 *
 * @note This is part of siklon project. (Siklon.c)
 *
 * <b>Description</b>
 *
 * This is a helper file for Siklon project. The functions in this file
 * are responsible to manage cyclone items found by the search procedures
 * in a double linked list array.
 *
 * Copyright (C) 2009 İsmail SEZEN
 *
 * <b>License</b>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "siklon_internal.h"
#include "array_helper.h"

/*! @name Double-linked list functions for Cyclone
 *  These functions are used to manipulte a double-linked list type of \ref cyclone_item.
 */
//@{//{

/*! @brief Creates a new cyclone_item and returns its pointer
 *  @return A pointer to new cyclone_item */
struct cyclone_item* cyclone_new() {
	struct cyclone_item* new_cyc = (struct cyclone_item*)xmalloc(sizeof(struct cyclone_item));
	new_cyc->next = NULL;
	new_cyc->prev = NULL;
	return new_cyc;
}

/*! @brief Creates a new cyclone_item and returns its pointer
 *
 *  This function creates a new cyclone_item and sets its member values to parameters.
 *
 *  @param[in] time Cyclone's time value
 *  @param[in] level Cyclone's level
 *  @param[in] height Cyclone's height
 *  @param[in] lat Cyclone's latitude
 *  @param[in] lon Cyclone's longtitude
 *  @return A pointer to new cyclone_item */
struct cyclone_item* cyclone_create(double time, int level, double height, double lat, double lon) {
	struct cyclone_item* new_cyc = cyclone_new();
	/*Set the cyclone values*/
	new_cyc->time = time;
	new_cyc->level = level;
	new_cyc->height = height;
	new_cyc->lat = lat;
	new_cyc->lon = lon;
	return new_cyc;
}

/*! @brief adds a cyclone to the end of double-linked cyclone list.
 *  @param[in] *item Cyclone to be add end of double-linked cylone list
 *  @param[in,out] **last Last element of double-linked Cyclone list.
 *  @return void */
void cyclone_add(struct cyclone_item* item, struct cyclone_item** last) {
	item->prev=(*last);
	if(!*last) *last = item;/*if first item, last item is this one*/
	else (*last)->next = item;/*else add item to end of the last*/
	item->next=NULL;
	*last = item;
}

/*! @brief Deletes the cyclone from the double-linked Cyclone list.
 *
 *  This function deletes the cyclone presented by \a item from the
 *  doule-linked Cyclone list.
 * @note You have to pass the \a first and \a last element pointers to the functon.
 *  @param[in] *item Cyclone to be removed from the double-linked cylone list
 *  @param[in] **first First element of double-linked Cyclone list.
 *  @param[in] **last Last element of double-linked Cyclone list.
 *  @return void */
void cyclone_delete(struct cyclone_item* item, struct cyclone_item** first, struct cyclone_item** last) {
	if(item->prev)//others except first
		item->prev->next = item->next;//set the next property of previous item to next item.
	else{//delete the first item
		*first = item->next;//first is the second one now on.
		if(*first) (*first)->prev = NULL;
	}

	if(item->next)//if others except last
		item->next->prev = item->prev;
	else{//delete last item
		*last = item->prev;
		if(*last) (*last)->next = NULL;
	}
	//
	free(item);
}

/*! @brief Deletes the cyclone from the double-linked Cyclone list.
 *
 *  This function replaces a new cyclone presented by \a item_new with
 *  another cyclone represented by \a item_old.
 * @note You have to pass the \a first and \a last element pointers to the functon.
 *  @param[in] *item_new New Cyclone that will be replaced with old one.
 *  @param[in] *item_old Old Cyclone item (This item will be deleted)
 *  @param[in] **first First element of double-linked Cyclone list.
 *  @param[in] **last Last element of double-linked Cyclone list.
 *  @return void */
void cyclone_overwrite(struct cyclone_item* item_new, struct cyclone_item** item_old,
					   struct cyclone_item** first, struct cyclone_item** last) {
	struct cyclone_item* prev = (*item_old)->prev;
	struct cyclone_item* next = (*item_old)->next;

	if(prev) prev->next = item_new;
	if(next) next->prev = item_new;

	item_new->prev = prev;
	item_new->next = next;
	if(*item_old == *last) *last = item_new;
	if(*item_old == *first) *first = item_new;

	free(*item_old);
	*item_old = item_new;
}

//}//@}
